/**
 *  Serponix is an arcade game in focus to multiplayer based on the classic game Snake.
 *  Copyright (C) 2010 - 2011  Daniel Vala
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License,
 *  or  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.

 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *  If you have any question do not hesitate to contact author
 *  on e-mail address: danielvala42@gmail.com
 */
package com.serponix.game.score;

import com.serponix.settings.SettingsFactory;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;
import javax.swing.JOptionPane;

/**
 * High-skore obsahuje 5 nejlepších výsledků.
 * Umí se uložit do souboru, načíst se ze souboru,
 * řadit skóre do TOP 5 a přehledně se zobrazit.
 * @author Daniel Vala
 */
public class HighSkore {

    private static final int MAXIMALNI_POCET_ZAZNAMU = 5;
    private static final String PATH;
    private static final String JMENO_SOUBORU = "high-skore.ser";
    private static List<ZaznamSkore> skoreList;

    static {
        PATH = SettingsFactory.getDirPath();
    }

    /**
     * Zapíše zadané skóre na jeho místo v TOP 5.
     * @param skore Počet bodů skóre.
     */
    public static void zapisSkore(int skore) {
        // nulové či záporné skóre se nikdy nikam nezapíše
        if (skore <= 0) {
            return;
        }

        // zobrazení dialogového okna pro zápis nicku
        String nick = JOptionPane.showInputDialog("Zadejejte své jméno", SettingsFactory.getNastaveniHry().getJmeno(0));

        // pokud neexistuje některý z potřebných adresářů nebo soubor high-skore.ser,
        // vytvoří se a do souboru se doplní do něj prázdné záznamy
        new File(PATH).mkdirs();
        if (!new File(PATH + JMENO_SOUBORU).exists()) {
            vytvorPrazdneSkore();
        } else {
            skoreList = nactiSkore();
        }
        zaradSkore(skore, nick);
        ulozSkore();

        zapisSkoreNaWeb(nick, skore);
    }

    /**
     * Zobrazí 5 nejlepších výsledků se jmény autorů.
     */
    public static void zobrazSkore() {
        new File(PATH).mkdirs();
        if (!new File(PATH + JMENO_SOUBORU).exists()) {
            vytvorPrazdneSkore();
            ulozSkore();
        } else {
            skoreList = nactiSkore();
        }
        JOptionPane.showMessageDialog(null, String.format("%-15s%-10s\n %-15s%-10s\n %-15s%-10s\n %-15s%-10s\n %-15s%-10s\n %-15s%-10s\n",
                " nick", "skore", skoreList.get(0).getNick(), skoreList.get(0).getSkore(), skoreList.get(1).getNick(), skoreList.get(1).getSkore(), skoreList.get(2).getNick(), skoreList.get(2).getSkore(), skoreList.get(3).getNick(), skoreList.get(3).getSkore(), skoreList.get(4).getNick(), skoreList.get(4).getSkore()), "TOP 5", JOptionPane.INFORMATION_MESSAGE);
    }

    /**
     * Vytvoří prázdné skóre bez jmen a záznamů o počtu bodů.
     */
    private static void vytvorPrazdneSkore() {
        // vytvoření seznamu pro uložení jednotlivých pozic skore
        skoreList = new LinkedList<ZaznamSkore>();
        for (int i = 0; i < MAXIMALNI_POCET_ZAZNAMU; i++) {
            skoreList.add(i, new ZaznamSkore("------", 0));
        }
        JOptionPane.showMessageDialog(null, "Byl vytvořen nový soubor " + JMENO_SOUBORU);
    }

    /**
     * Zařadí zadané skóre do TOP 5.
     * @param skore Skóre, které má být zařazeno.
     */
    private static void zaradSkore(int skore, String nick) {
        // pokud je dosažené skóre nižžší, než na poslední pozici, nezapíše se.
        if (skoreList.get(4).getSkore() >= skore) {
            return;
        }
        for (int i = 0; i < skoreList.size(); i++) {
            // jestliže je dosažené skóre větší, než na aktuálně prohledávaném místě, přidá se na tuto pozici a metoda se ukončí
            if (skore > skoreList.get(i).getSkore()) {
                skoreList.add(i, new ZaznamSkore(nick, skore));
                return;
            }
        }
        // přidá dosažené skóre na poslední místo
        skoreList.add(skoreList.size(), new ZaznamSkore(nick, skore));
    }

    @SuppressWarnings("unchecked")
    private static List<ZaznamSkore> nactiSkore() {
        ObjectInputStream input = null;
        List<ZaznamSkore> list = new LinkedList<ZaznamSkore>();
        try {
            input = new ObjectInputStream(new FileInputStream(PATH + JMENO_SOUBORU));
            list = (List<ZaznamSkore>) input.readObject();
        } catch (FileNotFoundException ex) {
            JOptionPane.showMessageDialog(null, "Soubor mapy nebyl nalezen.", "Chyba", JOptionPane.ERROR_MESSAGE);
        } catch (ClassCastException ex) {
            JOptionPane.showMessageDialog(null, "Chyba čtení souboru. Soubor high-skore nenbyl vytvořen v této hře. Prosím smažte jej." +
                    "\n Cesta k souboru: " + PATH + JMENO_SOUBORU, "Chyba", JOptionPane.ERROR_MESSAGE);
            System.exit(1);
        } catch (IOException ex) {
            JOptionPane.showMessageDialog(null, "Chyba čtení souboru. Soubor high-skore nebyl vytvořen v této hře. Prosím smažte jej." +
                    "\n Cesta k souboru: " + PATH + JMENO_SOUBORU, "Chyba", JOptionPane.ERROR_MESSAGE);
            System.exit(1);
        } catch (ClassNotFoundException ex) {
            JOptionPane.showMessageDialog(null, "Chyba při čtení souboru high-skore.", "Chyba", JOptionPane.ERROR_MESSAGE);
        } finally {
            try {
                input.close();
            } catch (IOException ex) {
                JOptionPane.showMessageDialog(null, "Chyba při zavírání souboru high-skore.", "Chyba", JOptionPane.ERROR_MESSAGE);
            }
        }
        return list;
    }

    private static void ulozSkore() {
        ObjectOutputStream output = null;
        try {
            output = new ObjectOutputStream(new FileOutputStream(new File(PATH + JMENO_SOUBORU)));
            output.writeObject(skoreList);
        } catch (FileNotFoundException ex) {
            JOptionPane.showMessageDialog(null, "Ověřte, že máte do oprávnění do složky " + PATH, "Chyba", JOptionPane.ERROR_MESSAGE);
        } catch (IOException ex) {
            JOptionPane.showMessageDialog(null, "Ověřte, že máte do oprávnění do složky " + PATH, "Chyba", JOptionPane.ERROR_MESSAGE);
        } finally {
            try {
                if (output != null) {
                    output.close();
                }
            } catch (IOException ex) {
                JOptionPane.showMessageDialog(null, "Chyba při zavírání souboru high-skore.", "Chyba", JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    private static void zapisSkoreNaWeb(String nick, int skore) {
        URL url = null;
        try {
            url = new URL("http://www.serponix.com/zapisVysledek?afgipkpokograj=" + nick + "&kgrajpogajfdae=" + skore);
        } catch (MalformedURLException ex) {
            System.err.println("chyba URL");
        }
        try {
            url.getContent();
        } catch (IOException ex) {
            System.err.println("IO chyba");
        }
    }
}
